/*
 * just like linux re create the stdio
 */
/*
 * this is the standard c libary.
 */
#include <stdarg.h>
#include <stddef.h>


//#include <kernel.h>
#define ZEROPAD 	1
#define SIGN 		2
#define PLUS 		4
#define SPACE 		8
#define LEFT 		16
#define SPECIAL 	32
#define SMALL 		64
char buf[1024];
#define div_n(n,base)  ({  \
		int res; \
		__asm__("divl %4":"=a"(n),"=d"(res):"0"(n),"1"(0),"r"(base));\
		res;\
		})
#define is_digit(a) ((a)>='0' && (a)<='9')

static int skip_atoi(const char **s)
{
	int i=0;
	while(is_digit(**s))
		i=i*10+*((*s)++)-'0';   //this is awesome code;
	return i;
}
static char * number(char *str,int num,int base,int size,int precision,int type)
{
	char c,sign,tmp[36];
	const char *digits="0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int i;

	if(type&SMALL) digits="0123456789 abcdefghijklmnopqrstuvwxyz";
	if(type&LEFT) type &= ~ZEROPAD;
	if(base<2 || base >36)
		return 0;
	c=(type & ZEROPAD )?'0':' ';
	if(type&SIGN &&num<0){
		sign='-';
		num=-num;
	}else
		sign=(type&PLUS)?'+':((type&SPACE)?' ':0);
	if(sign) size--;
	if(type&SPECIAL)
		if(base==16) size-=2;
		else if(base ==8) size--;
	i=0;
	if(num==0)
		tmp[i++]='0';
	else while(num!=0)
		tmp[i++]=digits[div_n(num,base)];
	if(i>precision) precision=i;
	size -=precision;
	if(!(type&(ZEROPAD+LEFT)))
		while(size-->0)
			*str++=' ';
	if(sign)
		*str++=sign;
	if(type &SPECIAL)
		if(base ==8 )
			*str++='0';
		else if(base ==16){
			*str++='0';
			*str++=digits[33];
		}
	if(!(type&LEFT))
		while(size-->0)
			*str++=c;
	while(i<precision--)
		*str++='0';
	while(i-->0)
		*str++=tmp[i];
	while(size-->0)
		*str++=' ';
	return str;
}
/*
 * 
 * i would like to say we need much more better ability to do such a job;
 * 有些不明就里
 */
int vsprintf1(char *buf,const char *fmt,va_list args)
{
	int 	len;
	int 	i;
	char 	*str;
	char 	*s;
	int 	*ip;

	int 	flags;
	int 	field_width;
	int 	precision;
	int 	qualifier;
/*
 * 来个循环来存储需要的东西
 */
	for(str=buf;*fmt;fmt++)
	{
		if(*fmt!="%"){
			*str++=*fmt;
			continue;
		}
		flags=0;
repeat:
		++fmt;
		switch(*fmt){
			case '-': flags|=LEFT;  	goto repeat;
			case '+': flags|=PLUS; 		goto repeat;
			case ' ': flags|=SPACE; 	goto repeat;
			case '#': flags|=SPECIAL;  	goto repeat;
				  //空符号为什么不可以写入
			//case '':  flags|=ZEROPAD; 	goto repeat;
			default: flags|=ZEROPAD;        goto repeat;
		}

		field_width=-1;
		if(is_digit(*fmt))
			field_width=skip_atoi(&fmt);
		//why fmt =* is the symbol that next args
		else if(*fmt++=='*')
		{
			field_width=va_arg(args,int);
			if(field_width<0){
				field_width=-field_width;
				flags|=LEFT;
			}
		}
	precision=-1;
	if(*fmt=='.')
	{
		++fmt;
		if(is_digit(*fmt))
			precision=skip_atoi(&fmt);
		else if(*fmt++=='*')
			precision=va_arg(args,int);
		if(precision<0)
			precision=0;
	}
	qualifier=-1;
	if(*fmt  == 'h' || *fmt =='1' || *fmt =='L')
	{
		qualifier = *fmt;
		++fmt;
	}
	switch(*fmt)
	{
		case 'c':
			if(!(flags&LEFT))
				while(--field_width>0)
					*str++=' ';
			*str++=(unsigned char) va_arg(args,int);
			while(--field_width>0)
				*str++=' ';
			break;

		case 's':
			s=va_arg(args,char *);
			len=strlen(s);
			if(precision<0)
				precision=len;
			else if(len>precision)
				len=precision;
			if(!(flags&LEFT))
				while(len<field_width--)
					*str++=' ';
			for(i=0;i<len;i++)
				*str++=*s++;
			while(len<field_width--)
				*str++=' ';
			break;
		case 'o':
			str=number(str,va_arg(args,unsigned long),8,field_width,precision,flags);
			break;
		case 'p': //pointer types
			if(field_width == -1){
				field_width=8;
				flags|=ZEROPAD;
			}
			str=number(str,(unsigned long )va_arg(args,void*),16,field_width,precision,flags);
			break;
		case 'x':
			flags|=SMALL;
		case 'X':
			str=number(str,va_arg(args,unsigned long),16,field_width,precision,flags);
			break;
		case 'd':

		case 'i':
			flags|=SIGN;
		case 'u':
			str=number(str,va_arg(args,unsigned long),10,field_width,precision,flags);
			break;
		case 'n':
			ip=va_arg(args,int *);
			*ip=(str-buf);
			break;
		default:
			if(*fmt!='%')
				*str++='%';
			if(*fmt)
				*str++=*fmt;
			else 
				--fmt;
			break;
	}
	}
	*str='\0';
	return str-buf;

}
int print(const char *fmt,...)
{
	va_list args;
	int i;
	va_start(args,fmt);
	i=vsprintf(buf,fmt,args);
	va_end(args);
	__asm__(
			"push %%fs \n\t"
			"push %%ds \n\t"
			"pop  %%fs\n\t"
			"pushl 	%0\n\t"
			"pushl 	$buf \n\t"
			"pushl  $0 \n\t"
	//		"call 	tty_write \n\t"
			"addl 	$8,%%esp \n\t"
			"popl  	%0 \n\t"
			"pop    %%fs \n\t"
			::"r"(i):"ax","cx","dx");
	return i;
}
/* this is the test
int main()
{
	int x=100;
	div_n(x,19);
	printf("%d\n",x);
	printf("%d\n",'*');
	return 0;
}
*/
